﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using System.Xml.Linq;

namespace Sunny.Lib
{
    public static class XMLSerializerHelper
    {
        public static string Serialize<T>(T instance)
        {
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            return Serialize<T>(instance, ns, true);
        }

        public static string Serialize<T>(T instance, XmlSerializerNamespaces ns, bool omitXmlDeclaration)
        {
            if (instance == null)
                throw new ArgumentException("Serize object is null");

            StringBuilder sb = new StringBuilder();

            XmlWriterSettings writerSetting = new XmlWriterSettings();
            writerSetting.OmitXmlDeclaration = omitXmlDeclaration;
            writerSetting.Indent = true;

            using (XmlWriter xmlWriter = XmlWriter.Create(sb, writerSetting))
            using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(writer, instance, ns);
            }

            return sb.ToString();
        }

        public static T Deserialize<T>(string xmlText)
        {
            if (string.IsNullOrEmpty(xmlText))
                throw new ArgumentException("Deserialize object is null");

            T instance;

            using (XmlReader xmlReader = XmlReader.Create(new StringReader(xmlText)))
            using (XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(xmlReader))
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                instance = (T)serializer.Deserialize(reader);
            }

            return instance;
        }

        public static string SerializeObject(this object obj, Encoding encoding)
        {
            if (obj == null)
            {
                return null;
            }

            var ser = new XmlSerializer(obj.GetType());

            using (var ms = new MemoryStream())
            using (var xw = new XmlTextWriter(ms, encoding))
            {
                ser.Serialize(xw, obj);
                byte[] buffer = new byte[ms.Length];
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(buffer, 0, buffer.Length);
                return encoding.GetString(buffer);
            }
        }

        public static void CheckNotNull(this object val, string name)
        {
            if (val == null)
            {
                throw new ApplicationException(
                    string.Format(
                    "{0} should not be null.",
                    name));
            }
        }
        public static T DeserializeToObject<T>(this string xml)
        {
            xml.CheckNotNull("xml");
            var ser = new XmlSerializer(typeof(T));
            using (var stringReader = new StringReader(xml))
            using (var xmlTextReader = new XmlTextReader(stringReader))
            {
                return (T)ser.Deserialize(xmlTextReader);
            }
        }
    }

    public static class XMLSerializerHelperTest
    {
        public static void Test()
        {
            Person person1 = new Person()
            {
                FirstName = "Sunny",
                LastName = "Sun",
                Sex = "Man",
                Addresses = new List<Address>()
                { 
                    new Address()
                    {
                        City = "Shanghai",
                        CountryCode = "CN"
                    },
                    new Address()
                    {
                        City = "Beijin",
                        CountryCode = "CN"
                    }
                },
            };

            
            //string docString = new XDeclaration("1.0", "utf-8", null).ToString();
            /*XElement element = new XElement("alipay",
                    new XElement("is_success", "1212"),
                    new XElement("request",
                        new XElement("param", new XAttribute("name", "user_id"), "1212"),
                        new XElement("param", new XAttribute("name", "service"), "1212"),
                        new XElement("param", new XAttribute("name", "partner"), "1212"),
                        new XElement("param", new XAttribute("name", "no_coupon"), "1212"),
                        new XElement("param", new XAttribute("name", "trans_code"), "1212"),
                        new XElement("param", new XAttribute("name", "gmt_create_end"), "1212"),
                        new XElement("param", new XAttribute("name", "gmt_create_start"), "1212")),
                    new XElement("response",
                        new XElement("csv_result",
                            new XElement("count", "1212"),
                            new XElement("csv_data", "1212"))),
                    new XElement("sign", "1212"),
                    new XElement("sign_type", "1212"));
            XDocument XMLMsg = new XDocument(
                new XDeclaration("1.0", "utf-8", null),
                element);

            string responseStr = XMLMsg.Declaration.ToString() + XMLMsg.ToString(SaveOptions.DisableFormatting);

            xmlContent = responseStr = new XDeclaration("1.0", "utf-8", null).ToString() + xmlContent;*/
            string xmlDoc = XMLSerializerHelper.Serialize(person1);
            Person person2 = XMLSerializerHelper.Deserialize<Person>(xmlDoc);
            string xmlDoc1 = person1.SerializeObject(Encoding.ASCII);
            Person person3 = xmlDoc1.DeserializeToObject<Person>();

        }
    }

    public class Person
    {
        public Person()
        {
            Test1 = "Test1";
            Test2 = "Test2";
        }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Sex { get; set; }
        public List<Address> Addresses { get; set; }
        public string Email { get; set; }
        public string CellPhone { get; set; }

        protected string Test1 { get; set; }
        private string Test2 { get; set; }
    }

    public class Address
    {
        public string City { get; set; }
        public string CountryCode { get; set; }
        public string Street1 { get; set; }
    }
}
